package com.uam.web.common.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.uam.db.model.entity.RoutQueryModel;
import com.uam.utils.DateUtils;
import com.uam.utils.GeoTools;
import com.uam.utils.StringUtils;
import com.uam.web.common.vo.PointVo;
import com.uam.web.common.vo.RouteTrackVo;
import com.uam.web.common.vo.TaskVo;
import com.uam.web.common.vo.TrackPoint;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;

import java.math.BigDecimal;
import java.util.*;

/**
 * 航线计算相关统计
 *
 * @author Administrator
 */
@Slf4j
public class RouterUtils {
    public static RouteTrackVo getRouteTrackVo(JSONArray points, RoutQueryModel queryModel, long id, TaskVo taskVo) {
        RouteTrackVo routeTrackVo = new RouteTrackVo();
        routeTrackVo.setConflictFlag(false);
        int pointSize = points.size();
        List<PointVo> listPoint = new ArrayList<>(pointSize);
        List<Long> time = setPointsAndCountInfo(points, listPoint, routeTrackVo, queryModel);



        if(StringUtils.isNotBlank(queryModel.getAvoidancePoint())){
            JSONArray jsonArray=JSONArray.parseArray(queryModel.getAvoidancePoint());
            if(jsonArray !=null && jsonArray.size()>0){
                routeTrackVo.setConflictFlag(true);
            }
        }
        getNewPoint(time, points, routeTrackVo, listPoint,id,taskVo,queryModel);
        routeTrackVo.setPointVo(listPoint);
        return routeTrackVo;
    }

    /**
     * 计算当前飞行的位置的下表
     *
     * @param points
     * @param routeTrackVo
     */
    public static void getNewPoint(List<Long> time, JSONArray points,
                                   RouteTrackVo routeTrackVo,List<PointVo> listPoint,long id,TaskVo taskVo,RoutQueryModel queryModel) {
        int row = points.size();

        long nowTime = System.currentTimeMillis() / 1000;
        routeTrackVo.setIndexTime(nowTime);
        //默认第一个
        routeTrackVo.setIndex(0);
        //第一个
        TrackPoint start = points.getObject(0, TrackPoint.class);
        //最后一个
        TrackPoint end = points.getObject(row - 1, TrackPoint.class);

        Double cost=queryModel.getPredictCost() * 60;

        routeTrackVo.setTimes(cost.longValue());

        if (nowTime <= start.getTime()) {
            routeTrackVo.setIndex(0);
            return;
        }

        if (nowTime >= end.getTime()) {
            routeTrackVo.setIndex(row - 1);
            return;
        }

//        int index=  ClosestNumber.findClosestNumber(time, nowTime);

        int sIndex=0;
        int eIndex=0;
        Long sTime=0L;
        Long eTime=0L;
        PointVo sPoint=null;
        PointVo ePoint=null;
        int rowIndex=listPoint.size();
        for(int i=0;i<rowIndex-1;i++){
            int sIndexTemp=i;
            int eIndexTemp=i+1;
            PointVo sPointTemp= listPoint.get(sIndexTemp);
            PointVo ePointTemp= listPoint.get(eIndexTemp);
             sTime=Long.valueOf(sPointTemp.getPoints().get(2)+"");
             eTime=Long.valueOf(ePointTemp.getPoints().get(2)+"");

            if(nowTime>sTime && nowTime<=eTime){
                 sIndex=sIndexTemp;
                 eIndex=eIndexTemp;
                 sPoint=sPointTemp;
                 ePoint=ePointTemp;
                break;
            }
        }

        if(sIndex !=0 && eIndex !=0){
            double sL=Double.valueOf( sPoint.getPoints().get(0)+"");
            double sY=Double.valueOf( sPoint.getPoints().get(1)+"");

            double eL=Double.valueOf(ePoint.getPoints().get(0)+"");
            double eY=Double.valueOf( ePoint.getPoints().get(1)+"");


            long sTime1=Long.valueOf((listPoint.get(sIndex).getPoints().get(2)+""));
            long sTime2 = (nowTime - sTime1)/1000;

            double speed=Double.valueOf(sPoint.getPoints().get(3)+"");
            double speedM=speed * 1000 / 3600;

            //飞行距离
            double distanceTemp=speedM * (sTime2);

            //总距离
            double tempSum = RegionUtil.computeDistance(sL,sY, eL,eY);

            double reate=distanceTemp/tempSum;

            Coordinate[] line=new Coordinate[2];
            line[0]=new Coordinate();
            line[1]=new Coordinate();

            Coordinate  point= GeoTools.getPointOnLine(new Coordinate(sL,sY),new Coordinate(eL,eY),reate);
            if(point !=null) {
                List<Object> pointsTemp = new ArrayList<>(16);
                pointsTemp.add(point.x);
                pointsTemp.add(point.y);
                pointsTemp.add(nowTime);
                for (int i = 3; i < ePoint.getPoints().size(); i++) {
                    pointsTemp.add(ePoint.getPoints().get(i));
                }

                listPoint.add(eIndex, new PointVo(false, nowTime + "", pointsTemp));
            }
            routeTrackVo.setIndex(eIndex);
//            log.info(reate+"--reate 任务id：{}，位置：{}  经纬度：{}, 上一个：{},下一个：{}， 时间戳：{} 时间戳：" +
//                    "" + "{} 时间戳：{}",
//                    id,eIndex,point.x+","+point.y,sIndex,eIndex+1,
//                    DateUtils.getDateYYSs(new Date(Long.valueOf(listPoint.get(sIndex).getPoints().get(2)+"000"))),
//                    DateUtils.getDateYYSs(new Date(nowTime*1000)),
//                    DateUtils.getDateYYSs(new Date(Long.valueOf(listPoint.get(eIndex+1).getPoints().get(2)+"000"))));

          JSONArray jsonArray=new JSONArray(1024);

          StringBuffer stringBuffer=new StringBuffer("[");
          for(int i=0;i< listPoint.size();i++){
                PointVo pointVo=   listPoint.get(i);
                String s="{position: ["+pointVo.getPoints().get(0)+", "+pointVo.getPoints().get(1)+"],name: '"+i+( i==eIndex? "-添加点":"")+"',},";
                stringBuffer.append(s);
//                JSONArray jsonArray1=new JSONArray(3);
//                jsonArray1.add(pointVo.getPoints().get(0));
//                jsonArray1.add(pointVo.getPoints().get(1));
//                String name=;
//                JSONObject jsonObject =new JSONObject(12);
//                  jsonObject.put("position",jsonArray1);
//                  jsonObject.put("name",name);
//                  jsonArray.add(jsonObject);
          }
            stringBuffer.append("]");
//          log.info(" 补点id：{}",stringBuffer.toString());
        }

    }

    /**
     * 计算里程和统计点时长信息
     *
     * @param points
     * @param listPoint
     * @param routeTrackVo
     */
    public static List<Long> setPointsAndCountInfo(JSONArray points, List<PointVo> listPoint, RouteTrackVo routeTrackVo, RoutQueryModel queryModel) {
        double sum = 0.0;
        int row = points.size();
        TrackPoint current = null, last = null;
        List<Long> timeArray = new ArrayList<>(row);

        Map<String,Integer> keyMap=new HashMap<>(6);
        for (int i = 0; i < row; i++) {
            TrackPoint trackPointInfo = points.getObject(i, TrackPoint.class);
            listPoint.add(new PointVo(trackPointInfo,trackPointInfo.isConflictPoint(),trackPointInfo.getId()));
            timeArray.add(trackPointInfo.getTime());
            if (trackPointInfo.isConflictPoint()) {
                keyMap.put(trackPointInfo.getId(),i);
            }

            current = trackPointInfo;
            if (last != null) {
                double[] start = last.getPosition();
                double[] end = current.getPosition();
                double tempSum = RegionUtil.computeDistance(start[0], start[1], end[0], end[1]);
                sum += tempSum;
            }
            last = current;
        }
        TrackPoint one = points.getObject(0, TrackPoint.class);
        TrackPoint two = points.getObject(1, TrackPoint.class);
        sum = sum + two.getAltitude() - one.getAltitude();

        TrackPoint endOne = points.getObject(row - 1, TrackPoint.class);
        TrackPoint eneTwo = points.getObject(row - 2, TrackPoint.class);
        sum = sum + eneTwo.getAltitude() - endOne.getAltitude();


        double distance=queryModel.getActualDistance() <=1 ? queryModel.getPredictDistance():queryModel.getActualDistance();

        routeTrackVo.setDistance(new BigDecimal(distance).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());


//        List<List<PointVo>> listOldPoint= rectanglePoint(tempMap, points, listPoint, queryModel);

        JSONArray listOldPoint= rectanglePoint(queryModel,keyMap, listPoint);
        routeTrackVo.setAreaPointVo(listOldPoint);
        routeTrackVo.setRectanglePoint(queryModel.getRectanglePoint());
        return timeArray;
    }

    public static JSONArray rectanglePoint(RoutQueryModel queryModel ,Map<String,Integer> keyMap,List<PointVo> listPoint){
        if(StringUtils.isBlank(queryModel.getRectanglePoint()) || StringUtils.isBlank(queryModel.getAvoidancePoint())){
            return new JSONArray();
        }
        JSONArray jsonArray=JSONArray.parseArray(queryModel.getAvoidancePoint());
        if(jsonArray == null || jsonArray.size() ==0){
            return new JSONArray();
        }
        //在区域内有冲突
        boolean flag = CurrentListGroup.isInRectangle(jsonArray, queryModel.getRectanglePoint());
        if(flag){
            //取中间点
            JSONObject jsonObject=jsonArray.getJSONObject(1);
            String ownId=jsonObject.getString("id");
            Integer index=keyMap.get(ownId);

            //补点
            if(index !=null){
                JSONArray strArr = getAddPoint(index - 2, index, listPoint);
                Collections.reverse(strArr);
                jsonArray.addAll(0, strArr);
                jsonArray.addAll(getAddPoint(index + 2, index + 3, listPoint));
            }
            soutData(listPoint,jsonArray);
            return jsonArray;
        }
        return new JSONArray();
    }

    public static JSONArray getAddPoint(int startIndex,int endIndex,List<PointVo> listPoint){
        JSONArray jsonArrayStart=new JSONArray(16);
        try {
            List<PointVo> trackStart = listPoint.subList(startIndex, endIndex);
            trackStart.forEach(a -> {
                JSONObject jsonObjectStart = new JSONObject();
                jsonObjectStart.put("id", a.getId());
                JSONArray jsnTemp = new JSONArray();
                jsnTemp.add(a.getPoints().get(0));
                jsnTemp.add(a.getPoints().get(1));
                jsnTemp.add(a.getPoints().get(4));
                jsonObjectStart.put("position", jsnTemp);
                jsonArrayStart.add(jsonObjectStart);
            });
        }catch (Exception e){
            log.error("数据错误：{}",e.getMessage(),e);
        }
        return jsonArrayStart;
    }

    public static void soutData(List<PointVo> listPoint,JSONArray jsonArray){
        StringBuffer sbOld=new StringBuffer();
        listPoint.forEach(a->{
            sbOld.append(a.getPoints().get(0));
            sbOld.append(",");
            sbOld.append(a.getPoints().get(1));
            sbOld.append(";");
        });
        sbOld.deleteCharAt(sbOld.length()-1);


        StringBuffer sb=new StringBuffer();
        for(int i=0;i<jsonArray.size();i++) {
            JSONObject a=jsonArray.getJSONObject(i);
            sb.append(a.getJSONArray("position").getDouble(0));
            sb.append(",");
            sb.append(a.getJSONArray("position").getDouble(1));
            sb.append(";");
        }

        sb.deleteCharAt(sb.length()-1);
        System.out.println("计算前--"+sb.toString());
        System.out.println("计算后--"+sbOld.toString());
        System.out.println("-------------------------");
    }


    public static List<List<PointVo>> rectanglePoint(List<Integer> tempMap, JSONArray points, List<PointVo> listPoint, RoutQueryModel queryModel) {
        List<List<PointVo>> reList=new ArrayList<>();
        if (tempMap.size() == 0 || queryModel.getRectanglePoint() == null) {
            return reList;
        }
        List<List<Integer>> listIndex = CurrentListGroup.groupConsecutiveNumbers(tempMap);

        listIndex.forEach(a -> {
            //在区域内有冲突
            boolean flag = CurrentListGroup.isInRectangle(a, listPoint, queryModel.getRectanglePoint());
            if (flag) {
                List<PointVo> list=  CurrentListGroup.newPointsInfo(a,listPoint,queryModel.getFlightInterval());
                if(!list.isEmpty()) {
                    reList.add(list);
                }
            }
        });
        return reList;
    }
}
